#include "Epoll.h"

Epoll::Epoll()                                    // 在构造函数中创建了epollfd_。
{
    epollfd_ = epoll_create(1);
    if (epollfd_ == -1) {
        perror("epoll_create1() failed");
        exit(1);
    }
}

Epoll::~Epoll()                                // 在析构函数中关闭epollfd_。
{
    if (epollfd_ != -1) {
        close(epollfd_);
    }
}

// void Epoll::addfd(int fd, uint32_t op)               // 把fd和它需要监视的事件添加到红黑树上。
// {
//     struct epoll_event ev;
//     ev.events = op;
//     ev.data.fd = fd;
    
//     if (epoll_ctl(epollfd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
//         perror("epoll_ctl() failed");
//         exit(1);
//     }
// }


void Epoll::updatechannel(Channel *ch)
{
    struct epoll_event ev;
    ev.data.ptr = ch;
    ev.events = ch->events();

    if(ch->inpoll()){//已经在树上就更新
        if(epoll_ctl(epollfd_,EPOLL_CTL_MOD,ch->fd(),&ev)==-1){
            perror("epoll_ctl error");
            exit(-1);
        }
    }else{// 添加
        if(epoll_ctl(epollfd_,EPOLL_CTL_ADD,ch->fd(),&ev)==-1){
            perror("epoll_ctl error");
            exit(-1); 
        }
        ch->setinepoll();
    }
}


void Epoll::delfd(int fd) {
    if (epoll_ctl(epollfd_, EPOLL_CTL_DEL, fd, nullptr) == -1) {
        perror("epoll_ctl(EPOLL_CTL_DEL) failed");
        exit(1);
    }
}


// std::vector<epoll_event> Epoll::loop(int timeout)  // 运行epoll_wait()，等待事件的发生，已发生的事件用vector容器返回。
// {
//     bzero(events_,sizeof(events_));
//     std::vector<epoll_event> result;
//     int nfds = epoll_wait(epollfd_, events_, MaxEvents, timeout);
//     // 返回失败
//     if (nfds == -1) {
//         perror("epoll_wait() failed");
//         exit(1);
//     }
//     // 超时
//     if(nfds==0){
//         printf("wpoll wait timeout\n");
//         return result;
//     }
    
//     for (int i = 0; i < nfds; i++) {
//         result.push_back(events_[i]);
//     }
//     return result;
// }


std::vector<Channel*> Epoll::loop(int timeout)  // 运行epoll_wait()，等待事件的发生，已发生的事件用vector容器返回。
{
    bzero(events_,sizeof(events_));
    std::vector<Channel*> channels;
    int nfds = epoll_wait(epollfd_, events_, MaxEvents, timeout);
    // 返回失败
    if (nfds == -1) {
        perror("epoll_wait() failed");
        exit(1);
    }
    // 超时
    if(nfds==0){
        printf("wpoll wait timeout\n");
        return channels;
    }
    
    for (int i = 0; i < nfds; i++) {
        Channel *ch = (Channel*)events_[i].data.ptr;
        ch->setrevents(events_[i].events);
        channels.push_back(ch);
    }
    return channels;
}
